namespace Warehouse

open System
open Microsoft.Win32
open Microsoft.SqlServer.Management.Smo
open FSharp.Windows
open System.Windows

[<AbstractClass>]
type DatabaseMaintenanceController<'TFileDialog when 'TFileDialog :> FileDialog and 'TFileDialog : (new : unit -> 'TFileDialog)>(title) = 
    inherit Controller<DatabaseMaintenanceEvents, DatabaseMaintenanceModel>()

    let server = Server.FromConfigFile()

    member this.Server = server

    override this.InitModel model =
        model.Title <- title

    override this.Dispatcher = function
        | SelectFile -> Sync this.SelectFile        
        | Start -> 
            Sync(fun model ->
                model |> Validation.textRequired <@ fun m -> m.FileName @>
                if model.IsValid 
                then 
                    this.StartMaintenance model
            )

    member this.SelectFile model = 
        let fileDialog = new 'TFileDialog()
        fileDialog.FileName <- String.Format("{0}.{1:yyyyMMdd-HHmmss}", server.InitialCatalog, DateTime.Now)
        fileDialog.DefaultExt <- ".bak"
        fileDialog.Filter <- " (.bak)|*.bak"
        fileDialog.InitialDirectory <- server.BackupDirectory
        let result = fileDialog.ShowDialog()
        if result.HasValue && result.Value then
            model.FileName <- fileDialog.FileName

    abstract StartMaintenance : DatabaseMaintenanceModel -> unit 

type BackUpController(repository : DataModel.Repository) =  
    inherit DatabaseMaintenanceController<SaveFileDialog>("Back Up")

    override this.StartMaintenance model = 
        let backup = Backup(Action = BackupActionType.Database, Database = "Warehouse")
        backup.Devices.AddDevice(model.FileName, DeviceType.File) 
        backup.PercentCompleteNotification <- 10
        backup.PercentComplete.Add <| fun eventArgs -> 
            model.Progress <- double eventArgs.Percent
            model.ProgressText <- string eventArgs.Percent + " %"
        backup.SqlBackup this.Server

type RestoreController(repository : DataModel.Repository) =  
    inherit DatabaseMaintenanceController<OpenFileDialog>("Restore")

    override this.StartMaintenance model = 

        if MessageBox.ActionConfirmed("Restore operation will delete current database. Would you like to proceed?", "Restore database")
        then
            repository.Connection.Close()
            this.Server.KillDatabase "Warehouse"
            let restore = Restore(Action = RestoreActionType.Database, Database = "Warehouse")
            restore.Devices.AddDevice(model.FileName, DeviceType.File) 
            restore.PercentCompleteNotification <- 10
            restore.PercentComplete.Add <| fun eventArgs -> 
                model.Progress <- double eventArgs.Percent
                model.ProgressText <- string eventArgs.Percent + " %"
            restore.SqlRestore this.Server

